package com.xgf.demo.spring.aspect;

import com.xgf.demo.authorization.config.Constants;
import com.xgf.demo.configuration.WebInitProps;
import com.xgf.demo.entity.User;
import com.xgf.demo.exception.CheckException;
import com.xgf.demo.exception.UnloginException;
import com.xgf.demo.repository.UserRespository;
import com.xgf.demo.result.ResultBean;
import com.xgf.demo.spring.designpattern.DeleteStrategy;
import com.xgf.demo.spring.designpattern.SaveStrategy;
import com.xgf.demo.spring.designpattern.Strategy;
import com.xgf.demo.spring.designpattern.UpdateStrategy;
import com.xgf.demo.status.ResultStatus;
import com.xgf.demo.util.PackageUtil;
import com.xgf.demo.util.UserUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  2018/1/24
 * @Aututor xgf
 */

@Aspect
@Component
public class ControllerAspect {
    protected static org.slf4j.Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
    @Autowired
    private WebInitProps webInitProps;
    @Autowired
    private UserRespository userRespository;
    @Pointcut("execution(public * com.xgf.demo.controller..*.*(..))")
    public void web() {
    }

    /**
     * 需要自动填充变量功能
     * @param pjp
     * @return
     */
    public void ifAspect(ProceedingJoinPoint pjp){
        Object[] params = pjp.getArgs();
        String userId = UserUtil.getInstance().getUserId();
        Arrays.stream(params).forEach(param -> {
            /**
             * 如果包含在指定的类中，就把创建人，修改人的值赋值进去
             */
            if (param == null) {
                return;
            }
            String paramName = param.getClass().getName();
            if (PackageUtil.packageNames.contains(paramName)) {
                try {
                    Class<?> c = Class.forName(paramName);
                    Method[] method = param.getClass().getDeclaredMethods();
                    adaptionMethod(param, userId, pjp);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new CheckException(ResultStatus.PARAMS_ERROR);
                } finally {

                }
            }
        });
    }
    @Around("web()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();

        ResultBean<?> result;

        try {

            if(webInitProps.getIfAspect()){
                this.ifAspect(pjp);
            }

            result = (ResultBean<?>) pjp.proceed();

            logger.info(pjp.getSignature() + "   " + pjp.getSignature() + " 参数为  " + Arrays.toString(pjp.getArgs()) + " 成功");
            logger.info(pjp.getSignature() + "use time:" + (System.currentTimeMillis() - startTime));
        } catch (Throwable e) {
            result = handlerException(pjp, e);
        }

        return result;
    }

    public void adaptionMethod(Object param, String userId, ProceedingJoinPoint pjp) throws Exception {
        Method method = PackageUtil.adaptionMethod(pjp);
        String methodName = method.getName();
        /**
         * 之后改，这块写的low
         */
        Method m2 = null;
        /**
         *
         */
        for (Map.Entry<String, Strategy> entry : PackageUtil.methodMap.entrySet()) {
            if (methodName.startsWith(entry.getKey())) {
                doRequest(entry.getValue(),param,method,userId);
                return;
            }
       }


    }
    private  void doRequest(Strategy strategy,Object param, Method method, String userId) throws Exception{
        List<Method> methodList=strategy.adaptionMethod(param,method);
        User user = userRespository.findOne(Long.parseLong(userId));
        for (int i =0, size =methodList.size();i< size;i++ ){
            methodList.get(i).invoke(param, user);
        }

    }
    private ResultBean<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
        ResultBean<?> result = new ResultBean();
        logger.warn(pjp.getSignature() + "   " + e.getLocalizedMessage() + " 参数为  " + Arrays.toString(pjp.getArgs()));
        // 已知异常
        if (e instanceof CheckException) {
            result.setMsg(((CheckException) e).getMsg());
            result.setCode(((CheckException) e).getCode());
        } else if (e instanceof UnloginException) {
            result.setMsg("未登录");
            result.setCode(ResultStatus.USER_NOT_LOGIN.getCode());
        } else {
            logger.error(pjp.getSignature() + " error ", e);
            // TODO 未知的异常，应该格外注意，可以发送邮件通知等
            result.setMsg("执行异常");
            result.setCode(ResultStatus.FAIL.getCode());
        }

        return result;
    }

}